/*
//  JTPerlInterface.m
//  Agate Rule Tester
//
//  Created by Jim Turner on 11/20/05.

License: GNU General Public License
This program is free software; you can redistribute it and/or modify it under 
the terms of the GNU General Public License as published by the Free Software 
Foundation; either version 2 of the License, or (at your option) any later 
version.

This program is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
details.

You should have received a copy of the GNU General Public License along 
with this program; if not, write to the Free Software Foundation, Inc., 
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
http://www.gnu.org/licenses/licenses.html#GPL

*/

#import "JTPerlInterface.h"


@implementation JTPerlInterface

- (id) init
{
	if( self = [super init] )
	{
		[CBPerl stubInit:CBGetPerlArchver()];
		perl = [CBPerl sharedPerl];
		
		perlObj = [[NSClassFromString(@"PerlRegex") alloc] init];
	}
	
	return( self );
}

- (void) dealloc
{
	NSLog( @"JTPerlInterface dealloc" );

	[perlObj release];
	[perl release];
	[super dealloc];
}

- (NSString *) applyFind:(NSString *)find 
			  andReplace:(NSString *)replace 
			      onText:(NSString *)text 
		   caseSensitive:(BOOL) casesensitive 
			replaceFirst:(BOOL) replacefirst
			 replaceLast:(BOOL) replacelast
			  exhaustive:(BOOL) exhaustive
{
	NSString *fixedFind;
	NSString *fixedReplace;
	NSString *updatedString = text;

//	NSLog( @"find[%@] replace [%@] onText[%@] cS:[%d] rF[%d] rL[%d] ex[%d]", find, replace, text, casesensitive, replacefirst, replacelast, exhaustive );
	
	// First, fix special placeholders.  We upper-case what we received for find to test this as 
	// any variation of capitalization is accepted.
//	if( [find isEqualTo:@"[#begintext]"] )
	if( [[find uppercaseString] isEqualTo:@"[#BEGINTEXT]"] )
	{
		fixedFind = @"^";
	}
//	else if( [find isEqualTo:@"[#endtext]"] )
	else if( [[find uppercaseString] isEqualTo:@"[#ENDTEXT]"] )
	{
		fixedFind = @"$";
	}
	else
	{
		fixedFind    = [perlObj escapeRegexCharactersInExpression:[perlObj p_mnemonicToUnicode:find]];
	}
	
	fixedReplace = [perlObj escapeRegexCharactersInReplacement:[perlObj p_mnemonicToUnicode:replace]];

	// Everything's in Unicode now.  Case Sensitivity is handled in the regular expressions below (or in 
	// the actual perl routine).  DTI did case matches by upper-casing copies of everything (find, replace, 
	// and the original text) then using those positions to make the replacements of the original text in the
	// original data.  Kinda hokey to do the same when you can safely let perl's /i do it for you.

	// Find Last occurrence is the only wildcard from here.  We can't do a find last with 
	// regular expressions, so we'll make a special function for it.  But we need to do it last 
	// (because both find first and find last can be checked at the same time)
	if( !replacefirst && !replacelast )
	{
		// They want to replace every occurrence
		updatedString = [perlObj parseRegex:[NSString stringWithFormat:@"$ctr = $text =~ s/%@/%@/g%@", fixedFind, fixedReplace, (!casesensitive) ? @"i" : @"" ]
									 onText:updatedString
								 exhaustive:exhaustive];
	}
	else
	{
		// first/last replacements can't be exhaustive.  Duh, I know... but it's worth mentioning.
		if( replacefirst )
		{
			// Only difference is that we don't have a /g on the end
			updatedString = [perlObj parseRegex:[NSString stringWithFormat:@"$ctr = $text =~ s/%@/%@/%@", fixedFind, fixedReplace, (!casesensitive) ? @"i" : @""] 
										onText:updatedString 
									exhaustive:NO];
		}
		
		if( replacelast )
		{
			updatedString = [perlObj p_replaceLastWithFind:fixedFind 
											   withReplace:fixedReplace 
											        onText:updatedString 
											 caseSensitive:casesensitive];
		}
	}
	
	return( updatedString );

}


// This guy handles patterns that are coming in as complete regular expressions from the interface
// Regex's cannot be exhaustive (that's what /g is for)
- (NSString *) applyRegex:(NSString *)regex onText:(NSString *)text
{
	NSString *fixedRegex;
	NSString *updatedString;
	
	fixedRegex = [perlObj p_mnemonicToUnicode:regex];
	
	updatedString = [perlObj parseRegex:[NSString stringWithFormat:@"$text =~ %@", fixedRegex] onText:text exhaustive:NO];

	return( updatedString );
}

// Finds the number of matches a rule would find (for m// and // patterns)
- (int) matchRegex:(NSString *)regex onText:(NSString *)text
{
	NSString *fixedRegex;
	int matchFound;
	
	fixedRegex = [perlObj p_mnemonicToUnicode:regex];
	
	matchFound = [perlObj p_matchRegex:[NSString stringWithFormat:@"$matchFound = $text =~ %@", fixedRegex] onText:text];

	return( matchFound );
}


- (NSString *) showDTMnemonics:(NSString *)text
{
	NSString *updatedString;

	updatedString = [perlObj p_showDTMnemonics:text];
	
	return( updatedString );
}

- (NSString *) extractStoryText:(NSString *)rawText
{
	NSString *storyText;
	NSRange  searchRange;
	
	NSLog( @"storyText: %@", rawText );
	
	storyText = [perlObj extractStoryText:rawText];

	// storyText will have our error message, if there's one at all
	searchRange = [storyText rangeOfString:@"ERROR:" options:0 range:NSMakeRange(0,6)];
	if( searchRange.location == NSNotFound )
	{
		// No error, we are good to go
		lastExtractionStatus = YES;  // successful
		extractionError      = nil;
	}
	else
	{
		lastExtractionStatus = NO;  // not successful
		extractionError      = [NSString stringWithString:@"Failed to extract text from story"];
	}
	
	return( storyText );
}

- (BOOL) wasLastExtractionSuccessful
{
	return( lastExtractionStatus );
}

- (NSString *) extractionError
{
	return( extractionError );
}

- (NSString *)testRegex:(NSString *)regex
{
	NSString *tmpStr;
	NSString *fixedRegex;

	// Trim [#perl] if we need to
	if( (NSEqualRanges( [regex rangeOfString:@"[#perl]" options:NSAnchoredSearch], NSMakeRange( 0, 7 ) )) )
	{
		fixedRegex = [perlObj p_mnemonicToUnicode:[regex substringWithRange:NSMakeRange( 7, [regex length] - 7 )]];
	}
	else
	{
		fixedRegex = [perlObj p_mnemonicToUnicode:regex];
	}

	tmpStr = [perlObj doRegexTest:[NSString stringWithFormat:@"$testString =~ %@", fixedRegex]];

	return( tmpStr );
}

- (NSString *) convertTranslationToInDesign:(NSString *)text
{
	NSString *tmpStr;
	
	/* If the mnemonics are on, we need to remove the extra \015 we put in there
	   to clean up the output.  If the mnemonics aren't on, this won't change a thing.
	*/
	tmpStr = [perlObj parseRegex:[NSString stringWithString:@"$text =~ s/(\\[CR\\])\\015/$1/g"] onText:text exhaustive:NO];
	
	tmpStr = [perlObj p_mnemonicToUnicode:tmpStr];
	tmpStr = [perlObj p_unicodeToInDesign:tmpStr];
	
	return( tmpStr );
}

// Public accessor to the perl p_unicodeToMnemonic so that we can convert 
// raw characters entered by the user into DT thingers.
// I'd make this smarter, but the WireSpeed stuff is really stupid, so shall we be.
- (NSString *) unicodeToMnemonic:(NSString *)text
{
	return( [perlObj p_unicodeToMnemonic:text] );
}

@end
